package pogvue.analysis;

import pogvue.datamodel.Alignment;
import pogvue.datamodel.AlignmentI;
import pogvue.datamodel.Sequence;
import pogvue.datamodel.SequenceI;
import pogvue.util.Format;
import pogvue.io.FastaFile;

import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import java.io.IOException;

public class AlignmentUtil {

  private AlignmentUtil() {
  }

  public static int[][] percentIdentity2(AlignmentI align) {
    return percentIdentity2(align,0,align.getWidth()-1);
  }
 
  private static int[][] percentIdentity2(AlignmentI align, int start, int end) {
    int [][] cons2 = new int[align.getWidth()][24];
    // Initialize the array
    for (int j=0;j<24;j++) {
      for (int i=0; i < align.getWidth();i++) {
        cons2[i][j] = 0;
      }
    }
 
    return cons2;
  }

    public static int getPixelHeight(int i, int j,int charHeight) {
    int h=0;
    while (i < j) {
      h += charHeight;
      i++;
    }
    return h;
  }


    private static Vector substitution_rates (AlignmentI align, int start, int end) {

	Vector rates = new Vector();

	int len = (end-start+1);

	// Turn seqs into char arrays

	int[][] seqint = new int[align.getHeight()][len];


	for (int j = 0; j < align.getHeight(); j++) {

	    SequenceI seq = align.getSequenceAt(j);
	    
	    for (int i = 0 ; i < len; i++) {
		char c = seq.getCharAt(start + i - 1);

		if (c == 'A') {
		    seqint[j][i] = 0;
		} else if (c == 'C') {
		    seqint[j][i] = 1;
		} else if (c == 'T') {
		    seqint[j][i] = 2;
		} else if (c == 'G') {
		    seqint[j][i] = 3;
		} else {
		    seqint[j][i] = -1;
		}
		    
	    }

	}

	
	//	print_matrix(seqint,2,len);	for (int j = 0; j < align.getHeight(); j++) {

	    for (int j = 0; j < align.getHeight(); j++) {

		for (int k = 0; k < align.getHeight(); k++) {

		int counts[][] = new int[4][4];
		int tot  = 0;
		int tots[] = new int[4];
		int fulltot = 0;
		int fulltots[] = new int[4];
		
		for (int i = 0 ; i < len; i++) {
		    
		    if (k != j) {
			
			//			System.out.println("Seq " + j + " " + k + " " + i + " " + seqint[j][i] + " " + seqint[k][i]);
			if (seqint[j][i] >= 0 &&
			    seqint[k][i] >= 0) {
			    counts[seqint[k][i]][seqint[j][i]]++;
			    
			    //  print_matrix(counts,4,4);
			    tots[seqint[j][i]]++;
			    tot++;
			}
			if (seqint[j][i] != -1) {
			    fulltots[seqint[j][i]]++;
			    fulltot++;
			}
		    }
		}
		
		if (k != j) {

		    System.out.println();
		    
		    System.out.println("Sequence " + align.getSequenceAt(j).getName() + " "  + align.getSequenceAt(k).getName());

		    System.out.println();
		    print_matrix(counts,4,4);
		    System.out.println();


		    
		    double[][] out = new double[4][4];// = constant_multiply_matrix(counts,1.0/tot,4,4);
		    
		    for (int i = 0; i < 4; i++) {
			for (int jj = 0; jj < 4; jj++) {
			    out[i][jj] = (double)counts[i][jj]/tots[jj];
			}
		    }

		    print_matrix(out,4,4);
		    System.out.println();


		    System.out.print("RATES\t");
		    System.out.print(align.getSequenceAt(j).getName() + "\t"  + align.getSequenceAt(k).getName() + "\t");

		    for (int i = 0; i < 4; i++) {
			for (int jj = 0; jj < 4; jj++) {
			    Format.print(System.out,"%4.3f\t",out[i][jj]);
			}
		    }
		    System.out.println();

 		    for (int i = 0; i < 4; i++) {
			Format.print(System.out,"%4.3f\t", (double) fulltots[i] /fulltot);
		    }

		    System.out.println();		    
		    System.out.print("\nGC ");

		    Format.print(System.out,"%4.3f\t",(double)(100*fulltots[1]+fulltots[3])/fulltot);

		    System.out.print((fulltots[1]+fulltots[3]) + "\t" + fulltot);

		    
		    System.out.println();

		    rates.addElement(out);
		}
		
	    }
	}
	return rates;
    }
    
    public static double[][]  constant_multiply_matrix(int[][] matrix, double c,int n, int m) {
	double[][] out = new double[n][m];

	for (int i = 0; i < n; i++) {
	    for (int j = 0; j < m; j++) {
		
		out[i][j] = matrix[i][j]*c;
	    }
	}
	return out;
    }

	
    private static void print_matrix(int[][] matrix, int n, int m) {


	for (int i = 0; i < n; i++) {
	    for (int j = 0; j < m; j++) {

		System.out.print(matrix[i][j] + "\t");
	    }
	    System.out.println();
	}
    }
    private static void print_matrix(double[][] matrix, int n, int m) {


	for (int i = 0; i < n; i++) {
	    for (int j = 0; j < m; j++) {

		Format.print(System.out,"%4.3f\t",matrix[i][j]);

	    }
	    System.out.println();
	}
    }

    public static Hashtable findKmers(SequenceI seq, int start, int end, Vector kmers) {

         Hashtable pos = new Hashtable();

         for (int j = 0; j < kmers.size(); j++) {

           String   kmer    = ((Sequence)kmers.elementAt(j)).getSequence();
           Sequence kmerseq = (Sequence)kmers.elementAt(j);

           if (end <= seq.getLength()) {

	       String str = seq.getSequence(start,end);

	       int i = 0;

	       while (str.indexOf(kmer,i) != -1) {

		   int coord = str.indexOf(kmer,i);

		   pos.put(coord, kmerseq.getLength());

		   i  = coord + 1;
		   
	       }
	   }        
         }
         return pos;
    }
    public static void main(String[] args) {

        if (args.length > 2 && args[2].equals("-r")) {
					try {
						FastaFile ff = new FastaFile(args[0],"File");
						SequenceI[] s = ff.getSeqsAsArray();

          	Alignment align = new Alignment(s);
     	    	AlignmentUtil.substitution_rates(align,1,align.getWidth());
					} catch (IOException e) {
						System.out.println("Exception reading " + args[0] + " in AlignmentUtil");
					}
				} else if (args[0].equals("-k")) {
          Vector kmers = new Vector();

          Sequence s1 = new Sequence("TATA box","TATAAA");
          Sequence s2 = new Sequence("CAAT box","CAAT");

          kmers.addElement(s1);
          kmers.addElement(s2);

          Sequence test = new Sequence("test","GGGTATAAAGGGCAATGGGCAATGGGTATAAA");
          Hashtable pos = AlignmentUtil.findKmers(test,1,test.getLength(),kmers);

          Enumeration keys = pos.keys();

          while (keys.hasMoreElements()) {
             Object intpos = keys.nextElement();
             System.out.println("Pos " + intpos + " " + pos.get(intpos));
          }
        }
    }

}
